package com.company.eos.controller;

import cn.dev33.satoken.annotation.SaCheckLogin;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import cn.hutool.json.JSONUtil;
import com.company.eos.mapper.AuditFlowMapper;
import com.company.eos.mapper.AuditLeaveMapper;
import com.company.eos.domain.AuditLeave;
import com.company.eos.service.AuditDetailService;
import com.company.eos.service.AuditFlowService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.hibernate.validator.constraints.Range;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import com.company.eos.common.util.PageUtils;
import com.company.eos.common.R;
import com.company.eos.controller.form.leave.DeleteLeaveByIdForm;
import com.company.eos.controller.form.leave.InsertLeaveForm;
import com.company.eos.controller.form.leave.SearchLeaveByIdForm;
import com.company.eos.controller.form.leave.SearchLeaveByPageForm;
import com.company.eos.service.AuditLeaveService;

import javax.annotation.Resource;
import javax.validation.Valid;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.HashMap;

/**
 * @author: Song, Wei
 * @date: 2022-03-26
 */
@Slf4j
@RestController
@RequestMapping("/leave")
@Tag(name = "员工请假Web接口")
public class AuditLeaveController {

    @Autowired
    private AuditLeaveService auditLeaveService;
    @Autowired
    private AuditFlowService auditFlowService;
    @Resource
    private AuditFlowMapper auditFlowMapper;
    @Autowired
    private AuditDetailService auditDetailService;
    @Resource
    private AuditLeaveMapper auditLeaveMapper;

    @PostMapping("/searchLeaveByPage")
    @Operation(summary = "查询请假分页数据")
    @SaCheckLogin
    public R searchLeaveByPage(@Valid @RequestBody SearchLeaveByPageForm form) {
        log.info("查询请假分页数据，参数：{}", form);
        @NotNull(message = "page不能为空") @Min(value = 1, message = "page不能小于1") Integer page = form.getPage();
        @NotNull(message = "length不能为空") @Range(min = 10, max = 50, message = "length必须在10~50之间") Integer length = form.getLength();
        int start = (page - 1) * length;
        HashMap param = JSONUtil.parse(form).toBean(HashMap.class);
        param.put("start", start);
        param.put("myId", StpUtil.getLoginIdAsInt());
        if (!(StpUtil.hasPermission("LEAVE:SELECT") || StpUtil.hasPermission("ROOT"))) {
            param.put("userId", StpUtil.getLoginIdAsInt());
        }
        PageUtils pageUtils = auditLeaveService.searchLeaveByPage(param);
        return R.ok().put("page", pageUtils);
    }

    @PostMapping("/insert")
    @Operation(summary = "添加请假记录")
    @SaCheckLogin
    public R insert(@Valid @RequestBody InsertLeaveForm form) {
        log.info("添加请假记录，参数：{}", form);
        // 验证结束时间是不是早于开始时间
        DateTime start = DateUtil.parse(form.getStart());
        DateTime end = DateUtil.parse(form.getEnd());
        if (start.isAfterOrEquals(end)) {
            return R.error("请假开始时间不能晚于或等于截止时间");
        }

        // 判断当前请假是否跟其他请假有交集
        HashMap<String, Object> param = new HashMap<String, Object>(3) {{
            put("userId", StpUtil.getLoginIdAsInt());
            put("start", form.getStart());
            put("end", form.getEnd());
        }};

        // 有交集
        if (auditLeaveService.searchContradiction(param)) {
            return R.error("当前请假申请与已有请假申请日期上有交集覆盖");
        }

        // 计算请假天数
        long hours = start.between(end, DateUnit.HOUR);
        String days = new BigDecimal(hours).divide(new BigDecimal(24), 1, RoundingMode.CEILING).toString();

        if (days.contains(".0")) {
            days = days.replace(".0", "");
        }
        if (days.equals("0")) {
            days = "0.1";
        }

        AuditLeave auditLeave = JSONUtil.parse(form).toBean(AuditLeave.class);
        auditLeave.setUserId(StpUtil.getLoginIdAsInt());
        auditLeave.setDays(days);

        int flowId = auditFlowService.insertLeaveAudit(auditLeave);
        auditDetailService.insertAuditLeave(auditLeave, auditFlowMapper.selectById(flowId));
        auditLeave.setFlowId(flowId);
        int rows = auditLeaveService.insert(auditLeave);
        return R.ok().put("rows", rows);

    }

    @DeleteMapping("/deleteLeaveById")
    @Operation(summary = "删除请假记录")
    @SaCheckLogin
    public R deleteLeaveById(@Valid @RequestBody DeleteLeaveByIdForm form) {
        log.info("删除请假记录，参数：{}", form);
        HashMap<String, Object> param = new HashMap<String, Object>(2) {{
            put("id", form.getId());
            put("userId", StpUtil.getLoginIdAsInt());
        }};
        AuditLeave auditLeave = auditLeaveMapper.selectById(form.getId());
        Integer flowId = auditLeave.getFlowId();
        int rows = auditLeaveService.deleteLeaveById(param);
        return R.ok().put("rows", rows);
    }

    @PostMapping("/searchLeaveById")
    @Operation(summary = "根据id查询请假数据")
    @SaCheckLogin
    public R searchLeaveById(@Valid @RequestBody SearchLeaveByIdForm form) {
        log.info("根据id查询请假数据，参数：{}", form);
        HashMap param = JSONUtil.parse(form).toBean(HashMap.class);
        if (!(StpUtil.hasPermission("LEAVE:SELECT") || StpUtil.hasPermission("ROOT"))) {
            param.put("userId", StpUtil.getLoginIdAsInt());
        }
        HashMap map = auditLeaveService.searchLeaveById(param);
        return R.ok(map);
    }

}
